/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.metamodel.dynamodb;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import org.apache.metamodel.data.DataSet;
import org.apache.metamodel.data.InMemoryDataSet;
import org.apache.metamodel.schema.Column;
import org.apache.metamodel.schema.ColumnType;
import org.apache.metamodel.schema.Table;
import org.apache.metamodel.util.SimpleTableDef;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.CreateTableResult;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProjectionType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
public class DynamoDbDataContextIntegrationTest {
private AmazonDynamoDB client;
@Before
public void before() throws Exception {
final String userHome = System.getProperty("user.home");
final String propertiesFilename = userHome + "/metamodel-integrationtest-configuration.properties";
final File file = new File(propertiesFilename);
Assume.assumeTrue(file.exists());
final Properties props = new Properties();
props.load(new FileReader(file));
final String accessKey = props.getProperty("dynamodb.accessKey");
final String secretKey = props.getProperty("dynamodb.secretKey");
Assume.assumeNotNull(accessKey, secretKey);
final Regions region = Regions.fromName(props.getProperty("dynamodb.region", Regions.DEFAULT_REGION.getName()));
final AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
final AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);
client = AmazonDynamoDBClientBuilder.standard().withRegion(region).withCredentials(credentialsProvider).build();
}
@After
public void after() {
if (client != null) {
client.shutdown();
}
}
@Test
public void testScenario1() throws Exception {
final String tableName = "MetaModel-" + UUID.randomUUID().toString();
final ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput(5l, 5l);
final Collection<AttributeDefinition> attributes = new ArrayList<>();
attributes.add(new AttributeDefinition("id", ScalarAttributeType.S));
attributes.add(new AttributeDefinition("counter", ScalarAttributeType.N));
final Collection<KeySchemaElement> keySchema = new ArrayList<>();
keySchema.add(new KeySchemaElement("id", KeyType.HASH));
// CreateDateIndex
final GlobalSecondaryIndex globalSecondaryIndex = new GlobalSecondaryIndex().withIndexName("counter_index")
.withProvisionedThroughput(provisionedThroughput).withKeySchema(new KeySchemaElement()
.withAttributeName("counter").withKeyType(KeyType.HASH)).withProjection(new Projection()
.withProjectionType(ProjectionType.INCLUDE).withNonKeyAttributes("foundation"));
final CreateTableRequest createTableRequest = new CreateTableRequest();
createTableRequest.setTableName(tableName);
createTableRequest.setAttributeDefinitions(attributes);
createTableRequest.setGlobalSecondaryIndexes(Arrays.asList(globalSecondaryIndex));
createTableRequest.setKeySchema(keySchema);
createTableRequest.setProvisionedThroughput(provisionedThroughput);
final CreateTableResult createTableResult = client.createTable(createTableRequest);
// await the table creation to be "done".
{
String tableStatus = createTableResult.getTableDescription().getTableStatus();
while (!"ACTIVE".equals(tableStatus)) {
System.out.println("Waiting for table status to be ACTIVE. Currently: " + tableStatus);
Thread.sleep(300);
tableStatus = client.describeTable(tableName).getTable().getTableStatus();
}
}
client.putItem(tableName, createItem("id", "foo", "counter", 1, "foundation", "Apache"));
client.putItem(tableName, createItem("id", "bar", "counter", 2, "project", "MetaModel"));
client.putItem(tableName, createItem("id", "baz", "counter", 3, "url", "http://metamodel.apache.org"));
final SimpleTableDef[] tableDefs = new SimpleTableDef[] { new SimpleTableDef(tableName, new String[] {
"counter", "project" }, new ColumnType[] { ColumnType.INTEGER, ColumnType.STRING }) };
try {
try (final DynamoDbDataContext dc = new DynamoDbDataContext(client, tableDefs)) {
final Table table = dc.getTableByQualifiedLabel(tableName);
assertEquals(tableName, table.getName());
// Right now we can only discover indexed columns
assertEquals("[id, counter, project, foundation]", Arrays.toString(table.getColumnNames()));
final Column idColumn = table.getColumnByName("id");
assertEquals(true, idColumn.isPrimaryKey());
assertEquals(true, idColumn.isIndexed());
assertEquals(ColumnType.STRING, idColumn.getType());
assertEquals("Primary index member ('HASH' type)", idColumn.getRemarks());
final Column counterColumn = table.getColumnByName("counter");
assertEquals(ColumnType.NUMBER, counterColumn.getType());
assertEquals(true, counterColumn.isIndexed());
assertEquals(false, counterColumn.isPrimaryKey());
assertEquals("counter_index member ('HASH' type)", counterColumn.getRemarks());
final Column projectColumn = table.getColumnByName("project");
assertEquals(ColumnType.STRING, projectColumn.getType());
assertEquals(false, projectColumn.isIndexed());
assertEquals(false, projectColumn.isPrimaryKey());
assertEquals(null, projectColumn.getRemarks());
final Column foundationColumn = table.getColumnByName("foundation");
assertEquals(null, foundationColumn.getType());
assertEquals(false, foundationColumn.isIndexed());
assertEquals(false, foundationColumn.isPrimaryKey());
assertEquals("counter_index non-key attribute", foundationColumn.getRemarks());
try (final DataSet dataSet = dc.query().from(table).select("id", "counter", "project").orderBy("id")
.execute()) {
assertTrue(dataSet.next());
assertEquals("Row[values=[bar, 2, MetaModel]]", dataSet.getRow().toString());
assertTrue(dataSet.next());
assertEquals("Row[values=[baz, 3, null]]", dataSet.getRow().toString());
assertTrue(dataSet.next());
assertEquals("Row[values=[foo, 1, null]]", dataSet.getRow().toString());
assertFalse(dataSet.next());
}
try (final DataSet dataSet = dc.query().from(tableName).select("counter", "project").where("id").eq(
"baz").execute()) {
assertTrue(dataSet instanceof InMemoryDataSet);
assertTrue(dataSet.next());
assertEquals("Row[values=[3, null]]", dataSet.getRow().toString());
assertFalse(dataSet.next());
}
}
} finally {
client.deleteTable(tableName);
}
}
// convenience method
private Map<String, AttributeValue> createItem(Object... keyAndValues) {
final Map<String, AttributeValue> map = new HashMap<>();
for (int i = 0; i < keyAndValues.length; i = i + 2) {
final String key = (String) keyAndValues[i];
final Object value = keyAndValues[i + 1];
map.put(key, DynamoDbUtils.toAttributeValue(value));
}
return map;
}
}